#ifndef __AVR_CORE__
#define __AVR_CORE__

#include <iostream>
#include <inttypes.h>
#include <vector>

#include "clock-source.h"
#include "data-bus.h"
#include "flash-memory.h"
#include "sram.h"
#include "operations.h"
#include "integral.h"

using namespace std;

class CoreOperation;
typedef enum {
  C_FLAG = 0,
  Z_FLAG,
  N_FLAG,
  V_FLAG,
  S_FLAG,
  H_FLAG,
  T_FLAG,
  I_FLAG
} SREG_Flags;

class AVRCore : public ClockObserver, public DataBusMember
{
public:
  AVRCore (FlashMemory& program_memory, uint16_t address_map);

  void reset ();
  void add_operation (CoreOperation* op);

  uint16_t get_sp () const { return _sp; }
  void set_sp (uint16_t sp) { _sp = sp; }
  UInt8 get_sreg () const { return _sreg; }
  void set_sreg (const UInt8& sreg) { _sreg = sreg; }
  uint16_t get_pc () const { return _pc; }
  void set_pc (uint16_t pc) { _pc = pc; }
  void inc_pc (uint16_t inc) { _pc += inc; }
  FlashMemory& get_flash () const { return _program_memory; }

  virtual void clock_tick ();

  virtual uint8_t read (uint16_t address);
  virtual void write (uint16_t address, uint8_t data);

  /* Debugging methods */
  void dump_status (ostream& os);
  /* This method stores instruction into program memory at PC and
   * executes it */
  void execute_instruction (uint16_t instruction);

private:
  uint16_t _sp; /* Stack pointer */
  UInt8 _sreg; /* Status register */
  uint16_t _pc; /* Program counter */
  int _cskip;
  FlashMemory& _program_memory;
  CoreOperation* _cur_op;

  vector<CoreOperation*> _ops;
};

#endif /* __AVR_CORE__ */
